package cn.edu.pku.cs08.liudun.picventure.view;

import cn.edu.pku.cs08.liudun.picventure.AppConfig;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class MaskDispalyAreaView extends View {
	private static final String TAG = "MaskDispalyAreaView";
	
	int paintWidth = AppConfig.PAINT_INITIAL_WIDTH;
	int canvasWidth, canvasHeight;
	float lastX, lastY, tmpX, tmpY;
	public Bitmap maskBmp = null;
	public Bitmap displayBmp = null;
	Matrix scaleBmpMatrix = null;
	Matrix scalePathMatrix = null;
	
	Paint highlightPaint = null;
	Paint dimPaint = null;
	Paint erasePaint = null;
	Paint drawPaint = null;
	Paint onDrawPaint = null;
	
	Path mPath = null;
	Path mScaledPath = null;
	Canvas mCanvas = null;
	RectF displayScreenRectF = null;
	RectF maskBmpRectF = null;
	
	
	AppConfig appConfig = null;
	
	public MaskDispalyAreaView(Context context) {
		super(context);
		init();
	}

	public MaskDispalyAreaView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}
	
	public MaskDispalyAreaView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}
	
	private void init() {
		Log.e(TAG, "init");
		mCanvas = new Canvas();
		
		highlightPaint = new Paint();
		highlightPaint.setColor(Color.GREEN);		
		highlightPaint.setStyle(Paint.Style.STROKE);
		highlightPaint.setStrokeWidth(AppConfig.PAINT_INITIAL_WIDTH);
		
		dimPaint = new Paint();		
		dimPaint.setColor(Color.RED);
		dimPaint.setStyle(Paint.Style.STROKE);
		dimPaint.setStrokeWidth(AppConfig.PAINT_INITIAL_WIDTH);
		
		erasePaint = new Paint();
		erasePaint.setColor(Color.WHITE);
		erasePaint.setStyle(Paint.Style.STROKE);
		erasePaint.setStrokeWidth(AppConfig.PAINT_INITIAL_WIDTH);
		
		onDrawPaint = new Paint();		
		onDrawPaint.setAlpha(0x40);
		
		mPath = new Path();
		mScaledPath = new Path();
		
		this.setDrawPaintAsHighlight();
		
		appConfig = (AppConfig) this.getContext().getApplicationContext();
		
		initBmp();
	}
	

	
	public void initBmp() {
		this.displayBmp = appConfig.getDisplayBmp();
		this.maskBmp = appConfig.getEmptyMaskBmp();
		mCanvas.setBitmap(maskBmp);
		mCanvas.drawPaint(erasePaint);
		initMatrix();
	}
	
	public void initMatrix() {
		if(this.maskBmp == null) {
			return;
		}
		scaleBmpMatrix = new Matrix();
		scalePathMatrix = new Matrix();
		scaleBmpMatrix.setRectToRect(this.getMaskBmpRectF(), 
				appConfig.getScrenRectF(), 
				Matrix.ScaleToFit.CENTER);
		if(scaleBmpMatrix.invert(scalePathMatrix) == false) {
			Log.e(TAG, "initMatrix: error");
		}
	}
	
	@Override
	public void onDraw(Canvas canvas) {
		Log.e(TAG, "onDraw");
		if(this.maskBmp == null) {
			Log.e(TAG, "null maskBmp");
			return;
		}
		canvas.drawBitmap(displayBmp, scaleBmpMatrix, onDrawPaint);
		canvas.drawBitmap(maskBmp, scaleBmpMatrix, onDrawPaint);
	}
	
	public void setPaintWidth(int paintWidth) {
		this.paintWidth = paintWidth;
		highlightPaint.setStrokeWidth(paintWidth);
		dimPaint.setStrokeWidth(paintWidth);
		erasePaint.setStrokeWidth(paintWidth);
	}
	
	public void setDrawPaintAsHighlight() {
		this.drawPaint = highlightPaint;
	}
	
	public void setDrawPaintAsDim() {
		this.drawPaint = dimPaint;
	}
	
	public void setDrawPaintAsErase() {
		this.drawPaint = erasePaint;
	}
	
	private RectF getMaskBmpRectF() {
		if(maskBmpRectF == null) {
			maskBmpRectF = new RectF(0, 0, maskBmp.getWidth()-1, maskBmp.getHeight()-1);
			Log.e(TAG, "getMaskBmpRectF: " + maskBmp.getWidth() + " " + maskBmp.getHeight());
		}
		return maskBmpRectF;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		float tmpX = event.getX();
		float tmpY = event.getY();
		Log.e(TAG, "x: " + tmpX + " y: " + tmpY);
		
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mPath.reset();
			mPath.moveTo(tmpX, tmpY);
			lastX = tmpX;
			lastY = tmpY;
			
			mCanvas.drawPath(mPath, drawPaint);
			break;
		case MotionEvent.ACTION_MOVE:
            mPath.quadTo(lastX, lastY, tmpX, tmpY);
            lastX = tmpX;
			lastY = tmpY;
            
			mPath.transform(scalePathMatrix, mScaledPath);
			mCanvas.drawPath(mScaledPath, drawPaint);
			this.invalidate();
			break;
		case MotionEvent.ACTION_UP:
			mPath.lineTo(lastX, lastY);
			
			mPath.transform(scalePathMatrix, mScaledPath);
			mCanvas.drawPath(mScaledPath, drawPaint);
			this.invalidate();
			mPath.reset();
			break;
		default:
			Log.e(TAG, "event.getAction out of expectation");
		}
		return true;
	}
}
